#pragma once

#include<iostream>
#include<string>
#include<queue>
#include<pthread.h>
using namespace std;

template <class T>
class BlockQueue
{
    static const int defaultnum=5;
public:
    BlockQueue(int maxcap=defaultnum):maxcap_(maxcap)
    {
        maxcap_=maxcap;
        pthread_mutex_init(&mutex_,NULL);
        pthread_cond_init(&p_cond_,NULL);
        pthread_cond_init(&c_cond_,NULL);
    }

    void push(const T &in)  //生产者
    {
        pthread_mutex_lock(&mutex_);

        while(q_.size()==maxcap_)  //满了，不要生产
        {
            pthread_cond_wait(&p_cond_,&mutex_);
        }

        q_.push(in);
        
        //if(q_.size()<low_water_)  pthread_cond_signal(&c_cond_);
        pthread_cond_signal(&c_cond_);
        pthread_mutex_unlock(&mutex_);
    }

    T pop()   //消费者
    {
        pthread_mutex_lock(&mutex_);

        while(q_.empty())  //空了，不要去消费，在这排队等
        {
            pthread_cond_wait(&c_cond_,&mutex_);
        }

        T out=q_.front();
        q_.pop();

        //if(q_.size()>high_water_)  pthread_cond_signal(&p_cond_);
        pthread_cond_signal(&p_cond_);
        pthread_mutex_unlock(&mutex_);

        return out;
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&p_cond_);
        pthread_cond_destroy(&c_cond_);
    }
private:
    queue<T>  q_;  //仓库队列
    int maxcap_;   //仓库容量/阻塞队列大小
    pthread_mutex_t mutex_;   //整个阻塞队列中只能有一个生产者或消费者，生产者和消费者也不能同时在队列中，因为无法判断生产者消费者何时访问队列中的同一个T
    pthread_cond_t p_cond_;
    pthread_cond_t c_cond_; 

    // int low_water_;
    // int high_water_;
};
